home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xmris / player.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  27KB  |  1,033 lines

  1. /*{{{  (C) 1992 Nathan Sidwell*/
  2. /*****************************************************************************
  3.             X M R I S V1.01
  4.             ---------------
  5.             (C) 1992 Nathan Sidwell
  6.  
  7. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  8. is in the public domain. Permission is granted to distribute and compile
  9. verbatim copies of this software for non-commercial, non-profit use,
  10. without fee. The software may be modified, provided that both the above copyright
  11. notice and this permission notice appear.
  12.  
  13. No guarantee is given as to the robustness or suitability of this
  14. software for your computer.
  15.  
  16. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  17. *****************************************************************************/
  18. /*}}}*/
  19. #include "xmris.h"
  20. /*{{{  void bounce_ball()*/
  21. extern void bounce_ball FUNCARGVOID
  22. /*
  23.  * throws, bounces, explodes & implodes the ball
  24.  * note that show_updates, does the ball ploting
  25.  */
  26. {
  27.   switch(player.ball.state)
  28.   {
  29.     /*{{{  case 0: (held)*/
  30.     case 0:
  31.       if(player.throw == 1)
  32.     {
  33.       CELL      *cptr;
  34.       unsigned  face;
  35.     
  36.       player.throw = 2;
  37.       player.ball.state = 1;
  38.       face = monster.list[0].face;
  39.       player.ball.cell.x = monster.list[0].cell.x;
  40.       player.ball.cell.y = monster.list[0].cell.y;
  41.       player.ball.offset.x = monster.list[0].offset.x + ball_throw[face].x;
  42.       player.ball.offset.y = monster.list[0].offset.y + ball_throw[face].y;
  43.       player.ball.count = ball_dir[face];
  44.       cptr = BOARDCELL(player.ball.cell.x, player.ball.cell.y);
  45.       switch(monster.list[0].dir)
  46.       {
  47.         /*{{{  case 0: (up)*/
  48.         case 0:
  49.           if(player.ball.offset.y > -(CELL_HEIGHT / 2))
  50.         /*EMPTY*/;
  51.           else if(cptr[-CELL_STRIDE].visit)
  52.         {
  53.           player.ball.offset.y += CELL_HEIGHT + GAP_HEIGHT;
  54.           player.ball.cell.y--;
  55.         }
  56.           else if(cptr[-CELL_STRIDE * 2].depths[1] - player.ball.offset.y >
  57.           CELL_HEIGHT / 2 + CELL_HEIGHT + GAP_HEIGHT)
  58.         {
  59.           player.ball.offset.y += (CELL_HEIGHT + GAP_HEIGHT) * 2;
  60.           player.ball.cell.y -= 2;
  61.         }
  62.           else if(player.ball.offset.y + CELL_HEIGHT / 2 <
  63.           cptr[0].depths[0])
  64.         player.ball.state = 0;
  65.           break;
  66.         /*}}}*/
  67.         /*{{{  case 1: (down)*/
  68.         case 1:
  69.           if(player.ball.offset.y < (CELL_HEIGHT / 2))
  70.         /*EMPTY*/;
  71.           else if(cptr[CELL_STRIDE].visit)
  72.         {
  73.           player.ball.offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  74.           player.ball.cell.y++;
  75.         }
  76.           else if(player.ball.offset.y - cptr[CELL_STRIDE * 2].depths[0] >
  77.           CELL_HEIGHT / 2 + CELL_HEIGHT + GAP_HEIGHT)
  78.         {
  79.           player.ball.offset.y -= (CELL_HEIGHT + GAP_HEIGHT) * 2;
  80.           player.ball.cell.y += 2;
  81.         }
  82.           else if(player.ball.offset.y - CELL_HEIGHT / 2 >
  83.           cptr[0].depths[1])
  84.         player.ball.state = 0;
  85.           break;
  86.         /*}}}*/
  87.         /*{{{  case 2: (left)*/
  88.         case 2:
  89.           if(player.ball.offset.x > -(CELL_WIDTH / 2))
  90.         /*EMPTY*/;
  91.           else if(cptr[-1].visit)
  92.         {
  93.           player.ball.offset.x += CELL_WIDTH + GAP_WIDTH;
  94.           player.ball.cell.x--;
  95.         }
  96.           else if(cptr[-2].depths[3] - player.ball.offset.x >
  97.           CELL_WIDTH / 2 + CELL_WIDTH + GAP_WIDTH)
  98.         {
  99.           player.ball.offset.x += (CELL_WIDTH + GAP_WIDTH) * 2;
  100.           player.ball.cell.x -= 2;
  101.         }
  102.           else if(player.ball.offset.x + CELL_WIDTH / 2 <
  103.           cptr[0].depths[2])
  104.         player.ball.state = 0;
  105.           break;
  106.         /*}}}*/
  107.         /*{{{  case 3: (right)*/
  108.         case 3:
  109.           if(player.ball.offset.x < (CELL_HEIGHT / 2))
  110.         /*EMPTY*/;
  111.           else if(cptr[1].visit)
  112.         {
  113.           player.ball.offset.x -= CELL_WIDTH + GAP_WIDTH;
  114.           player.ball.cell.x++;
  115.         }
  116.           else if(player.ball.offset.x - cptr[2].depths[2] >
  117.           CELL_WIDTH / 2 + CELL_WIDTH + GAP_WIDTH)
  118.         {
  119.           player.ball.offset.x -= (CELL_WIDTH + GAP_WIDTH) * 2;
  120.           player.ball.cell.x += 2;
  121.         }
  122.           else if(player.ball.offset.x - CELL_HEIGHT / 2 >
  123.           cptr[0].depths[3])
  124.         player.ball.state = 0;
  125.           break;
  126.         /*}}}*/
  127.       }
  128.       player.ball.pixel.x =
  129.           PIXELX(player.ball.cell.x, player.ball.offset.x) + CELL_WIDTH / 2;
  130.       player.ball.pixel.y =
  131.           PIXELY(player.ball.cell.y, player.ball.offset.y) + CELL_HEIGHT / 2;
  132.     }
  133.       break;
  134.     /*}}}*/
  135.     /*{{{  case 1: (bounce)*/
  136.     case 1:
  137.     {
  138.       int       i;
  139.       CELL      *cptr;
  140.     
  141.       cptr = BOARDCELL(player.ball.cell.x, player.ball.cell.y);
  142.       for(i = BALL_STEPS; i--;)
  143.     {
  144.       int       walls;
  145.       /* bit vector tl, br, bl, tr, t, b, l, r */
  146.     
  147.       /*{{{  moved to above or below cell?*/
  148.       if(player.ball.offset.y > CELL_HEIGHT / 2 &&
  149.           cptr[CELL_STRIDE].depths[0])
  150.         {
  151.           player.ball.offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  152.           player.ball.cell.y++;
  153.           cptr += CELL_STRIDE;
  154.         }
  155.       else if(player.ball.offset.y < -CELL_HEIGHT / 2 &&
  156.           cptr[-CELL_STRIDE].depths[1])
  157.         {
  158.           player.ball.offset.y += CELL_HEIGHT + GAP_HEIGHT;
  159.           player.ball.cell.y--;
  160.           cptr -= CELL_STRIDE;
  161.         }
  162.       /*}}}*/
  163.       /*{{{  moved to left or right cell?*/
  164.       if(player.ball.offset.x > CELL_WIDTH / 2 && cptr[1].depths[2])
  165.         {
  166.           player.ball.offset.x -= CELL_WIDTH + GAP_WIDTH;
  167.           player.ball.cell.x++;
  168.           cptr++;
  169.         }
  170.       else if(player.ball.offset.x < -CELL_WIDTH / 2 && cptr[-1].depths[3])
  171.         {
  172.           player.ball.offset.x += CELL_WIDTH + GAP_WIDTH;
  173.           player.ball.cell.x--;
  174.           cptr--;
  175.         }
  176.       /*}}}*/
  177.       walls = 0x00;
  178.       /*{{{  set the maze walls*/
  179.       {
  180.         unsigned  quadrant;
  181.         /* quadrants to, bo, lo, ro, ti, bi, li, ri, t, b, l, r */
  182.             
  183.         /* work out where we are in the cell */
  184.         quadrant = 0x000;
  185.         /*{{{  y place*/
  186.         if(player.ball.offset.y < -CELL_HEIGHT / 2 - VEL_Y)
  187.           quadrant |= 0x008;
  188.         else if(player.ball.offset.y < -CELL_HEIGHT / 2)
  189.           quadrant |= 0x800;
  190.         else if(player.ball.offset.y < -CELL_HEIGHT / 2 + VEL_Y)
  191.           quadrant |= 0x080;
  192.         else if(player.ball.offset.y >= CELL_HEIGHT / 2 + VEL_Y)
  193.           quadrant |= 0x004;
  194.         else if(player.ball.offset.y >= CELL_HEIGHT / 2)
  195.           quadrant |= 0x400;
  196.         else if(player.ball.offset.y >= CELL_HEIGHT / 2 - VEL_Y)
  197.           quadrant |= 0x040;
  198.         /*}}}*/
  199.         /*{{{  x place*/
  200.         if(player.ball.offset.x < -CELL_WIDTH / 2 - VEL_X)
  201.           quadrant |= 0x002;
  202.         else if(player.ball.offset.x < -CELL_WIDTH / 2)
  203.           quadrant |= 0x200;
  204.         else if(player.ball.offset.x < -CELL_WIDTH / 2 + VEL_X)
  205.           quadrant |= 0x020;
  206.         else if(player.ball.offset.x >= CELL_WIDTH / 2 + VEL_X)
  207.           quadrant |= 0x001;
  208.         else if(player.ball.offset.x >= CELL_WIDTH / 2)
  209.           quadrant |= 0x100;
  210.         else if(player.ball.offset.x >= CELL_WIDTH / 2 - VEL_X)
  211.           quadrant |= 0x010;
  212.         /*}}}*/
  213.         if(quadrant & 0x888)
  214.           /*{{{  above cell*/
  215.           {
  216.         if(player.ball.offset.y <=
  217.             cptr[0].depths[0] - CELL_HEIGHT / 2 + VEL_Y)
  218.           walls |= 0x98;
  219.         if(quadrant & 0x808)
  220.           {
  221.             unsigned  mask;
  222.                   
  223.             if(quadrant & 0x800)
  224.               mask = 0x93;
  225.             else
  226.               mask = 0xF3;
  227.             if(quadrant & 0x020)
  228.               walls |= mask & 0xA2;
  229.             if(quadrant & 0x010)
  230.               walls |= mask & 0x51;
  231.           }
  232.         else
  233.           {
  234.             if(quadrant & 0x020)
  235.               {
  236.             if(cptr[0].depths[0] >= -VEL_Y ||
  237.                 cptr[0].depths[2] >= -VEL_X ||
  238.                 cptr[-1].depths[0] >= -VEL_Y ||
  239.                 cptr[-CELL_STRIDE].depths[2] >= -VEL_X)
  240.               walls |= 0x80;
  241.               }
  242.             else if(quadrant & 0x010)
  243.               {
  244.             if(cptr[0].depths[0] >= -VEL_Y ||
  245.                 cptr[0].depths[3] <= VEL_X ||
  246.                 cptr[1].depths[0] >= -VEL_Y ||
  247.                 cptr[-CELL_STRIDE].depths[3] <= VEL_X)
  248.               walls |= 0x10;
  249.               }
  250.           }
  251.           }
  252.           /*}}}*/
  253.         else if(quadrant & 0x444)
  254.           /*{{{  below cell*/
  255.           {
  256.         if(player.ball.offset.y >=
  257.             cptr[0].depths[1] + CELL_HEIGHT / 2 - VEL_Y)
  258.           walls |= 0x64;
  259.         if(quadrant & 0x404)
  260.           {
  261.             unsigned  mask;
  262.                   
  263.             if(quadrant & 0x400)
  264.               mask = 0x63;
  265.             else
  266.               mask = 0xF3;
  267.             if(quadrant & 0x020)
  268.               walls |= mask & 0xA2;
  269.             if(quadrant & 0x010)
  270.               walls |= mask & 0x51;
  271.           }
  272.         else
  273.           {
  274.             if(quadrant & 0x020)
  275.               {
  276.             if(cptr[0].depths[1] <= VEL_Y ||
  277.                 cptr[0].depths[2] >= -VEL_X ||
  278.                 cptr[-1].depths[1] <= VEL_Y ||
  279.                 cptr[CELL_STRIDE].depths[2] >= -VEL_X)
  280.               walls |= 0x20;
  281.               }
  282.             else if(quadrant & 0x010)
  283.               {
  284.             if(cptr[0].depths[1] <= VEL_Y ||
  285.                 cptr[0].depths[3] <= VEL_X ||
  286.                 cptr[1].depths[1] <= VEL_Y ||
  287.                 cptr[CELL_STRIDE].depths[3] <= VEL_X)
  288.               walls |= 0x40;
  289.               }
  290.           }
  291.           }
  292.           /*}}}*/
  293.         if(quadrant & 0x222)
  294.           /*{{{  left cell*/
  295.           {
  296.         if(player.ball.offset.x <=
  297.             cptr[0].depths[2] - CELL_WIDTH / 2 + VEL_X)
  298.           walls |= 0xA2;
  299.         if(quadrant & 0x202)
  300.           {
  301.             unsigned  mask;
  302.                   
  303.             if(quadrant & 0x200)
  304.               mask = 0xAC;
  305.             else
  306.               mask = 0xFC;
  307.             if(quadrant & 0x080)
  308.               walls |= mask & 0x98;
  309.             if(quadrant & 0x040)
  310.               walls |= mask & 0x64;
  311.           }
  312.           }
  313.           /*}}}*/
  314.         else if(quadrant & 0x111)
  315.           /*{{{  right cell*/
  316.           {
  317.         if(player.ball.offset.x >=
  318.             cptr[0].depths[3] + CELL_WIDTH / 2 - VEL_X)
  319.           walls |= 0x51;
  320.         if(quadrant & 0x101)
  321.           {
  322.             unsigned  mask;
  323.                   
  324.             if(quadrant & 0x100)
  325.               mask = 0x5C;
  326.             else
  327.               mask = 0xFC;
  328.             if(quadrant & 0x080)
  329.               walls |= mask & 0x98;
  330.             if(quadrant & 0x040)
  331.               walls |= mask & 0x64;
  332.           }
  333.           }
  334.           /*}}}*/
  335.       }
  336.       /*}}}*/
  337.       /*{{{  set apple walls*/
  338.       {
  339.         unsigned  i;
  340.         APPLE     *aptr;
  341.             
  342.         for(aptr = apple.list, i = apple.apples; i--; aptr++)
  343.           {
  344.         int     x, y;
  345.         int     edge;
  346.         /* edge ot, ob, ol, or, t, b, l, r */
  347.               
  348.         if(aptr->state < 4)
  349.           {
  350.             x = aptr->pixel.x;
  351.             y = aptr->pixel.y;
  352.             edge = 0;
  353.             /*{{{  Y edge*/
  354.             if(player.ball.pixel.y - y < -VEL_Y ||
  355.             player.ball.pixel.y - y >= CELL_HEIGHT + VEL_Y)
  356.               /*EMPTY*/;
  357.             else if(player.ball.pixel.y - y < 0)
  358.               edge |= 0X80;
  359.             else if(player.ball.pixel.y - y < CELL_HEIGHT / 2)
  360.               edge |= 0X08;
  361.             else if(player.ball.pixel.y - y < CELL_HEIGHT)
  362.               edge |= 0x04;
  363.             else
  364.               edge |= 0x40;
  365.             /*}}}*/
  366.             /*{{{  X edge*/
  367.             if(player.ball.pixel.x - x < -VEL_X ||
  368.             player.ball.pixel.x - x >= CELL_WIDTH + VEL_X)
  369.               /*EMPTY*/;
  370.             else if(player.ball.pixel.x - x < 0)
  371.               edge |= 0X20;
  372.             else if(player.ball.pixel.x - x < CELL_WIDTH / 2)
  373.               edge |= 0X02;
  374.             else if(player.ball.pixel.x - x < CELL_WIDTH)
  375.               edge |= 0x01;
  376.             else
  377.               edge |= 0x10;
  378.             /*}}}*/
  379.             if(edge)
  380.               {
  381.             /*{{{  top*/
  382.             if(edge & 0X88 && edge & 0X33)
  383.               {
  384.                 if(edge & 0X03)
  385.                   walls |= 0X04;
  386.                 if(edge & 0X23)
  387.                   walls |= 0X40;
  388.                 if(walls & 0X13)
  389.                   walls |= 0X20;
  390.               }
  391.             /*}}}*/
  392.             /*{{{  bottom*/
  393.             if(edge & 0X44 && edge & 0X33)
  394.               {
  395.                 if(edge & 0X03)
  396.                   walls |= 0X08;
  397.                 if(edge & 0X23)
  398.                   walls |= 0X10;
  399.                 if(walls & 0X13)
  400.                   walls |= 0X80;
  401.               }
  402.             /*}}}*/
  403.             /*{{{  left*/
  404.             if(edge & 0X22 && edge & 0X0C)
  405.               {
  406.                 walls |= 0X01;
  407.                 if(edge & 0X8C)
  408.                   walls |= 0X40;
  409.                 if(walls & 0X4C)
  410.                   walls |= 0X10;
  411.               }
  412.             /*}}}*/
  413.             /*{{{  right*/
  414.             if(edge & 0X11 && edge & 0X0C)
  415.               {
  416.                 walls |= 0X02;
  417.                 if(edge & 0X8C)
  418.                   walls |= 0X20;
  419.                 if(walls & 0X4C)
  420.                   walls |= 0X80;
  421.               }
  422.             /*}}}*/
  423.               }
  424.           }
  425.           }
  426.       }
  427.       /*}}}*/
  428.       if((walls & 0xC) == 0xC || (walls & 0x03) == 0x03)
  429.         {
  430.           player.ball.state = 2;
  431.           player.ball.count = 0;
  432.           break;
  433.         }
  434.       else
  435.         {
  436.           /*{{{  bounce?*/
  437.           switch(player.ball.count)
  438.           {
  439.         /*{{{  case 0: (up left)*/
  440.         case 0:
  441.           if(!(walls & 0X80))
  442.             /*EMPTY*/;
  443.           else if((walls & 0X0A) == 0X08)
  444.             player.ball.count = 2;
  445.           else if((walls & 0X0A) == 0X02)
  446.             player.ball.count = 3;
  447.           else
  448.             player.ball.count = 1;
  449.           break;
  450.         /*}}}*/
  451.         /*{{{  case 1: (down right)*/
  452.         case 1:
  453.           if(!(walls & 0X40))
  454.             /*EMPTY*/;
  455.           else if((walls & 0X05) == 0X04)
  456.             player.ball.count = 3;
  457.           else if((walls & 0X05) == 0X01)
  458.             player.ball.count = 2;
  459.           else
  460.             player.ball.count = 0;
  461.           break;
  462.         /*}}}*/
  463.         /*{{{  case 2: (down left)*/
  464.         case 2:
  465.           if(!(walls & 0X20))
  466.             /*EMPTY*/;
  467.           else if((walls & 0X06) == 0X04)
  468.             player.ball.count = 0;
  469.           else if((walls & 0X06) == 0X02)
  470.             player.ball.count = 1;
  471.           else
  472.             player.ball.count = 3;
  473.           break;
  474.         /*}}}*/
  475.         /*{{{  case 3: (up right)*/
  476.         case 3:
  477.           if(!(walls & 0X10))
  478.             /*EMPTY*/;
  479.           else if((walls & 0X09) == 0X08)
  480.             player.ball.count = 1;
  481.           else if((walls & 0X09) == 0X01)
  482.             player.ball.count = 0;
  483.           else
  484.             player.ball.count = 2;
  485.           break;
  486.         /*}}}*/
  487.           }
  488.           /*}}}*/
  489.           /*{{{  move ball*/
  490.           switch(player.ball.count)
  491.           {
  492.         /*{{{  case 0: (up left)*/
  493.         case 0:
  494.           player.ball.offset.x -= VEL_X;
  495.           player.ball.offset.y -= VEL_Y;
  496.           player.ball.pixel.x -= VEL_X;
  497.           player.ball.pixel.y -= VEL_Y;
  498.           break;
  499.         /*}}}*/
  500.         /*{{{  case 1: (down right)*/
  501.         case 1:
  502.           player.ball.offset.x += VEL_X;
  503.           player.ball.offset.y += VEL_Y;
  504.           player.ball.pixel.x += VEL_X;
  505.           player.ball.pixel.y += VEL_Y;
  506.           break;
  507.         /*}}}*/
  508.         /*{{{  case 2: (down left)*/
  509.         case 2:
  510.           player.ball.offset.x -= VEL_X;
  511.           player.ball.offset.y += VEL_Y;
  512.           player.ball.pixel.x -= VEL_X;
  513.           player.ball.pixel.y += VEL_Y;
  514.           break;
  515.         /*}}}*/
  516.         /*{{{  case 3: (up right)*/
  517.         case 3:
  518.           player.ball.offset.x += VEL_X;
  519.           player.ball.offset.y -= VEL_Y;
  520.           player.ball.pixel.x += VEL_X;
  521.           player.ball.pixel.y -= VEL_Y;
  522.           break;
  523.         /*}}}*/
  524.           }
  525.           /*}}}*/
  526.         }
  527.     }
  528.       if(player.ball.state == 1)
  529.     /*{{{  hit a monster?*/
  530.     {
  531.       unsigned  i;
  532.       MONSTER   *mptr;
  533.         
  534.       for(mptr = monster.list, i = monster.monsters; i--; mptr++)
  535.         if(!mptr->shot && !mptr->apple &&
  536.         player.ball.pixel.x - mptr->pixel.x >= 0 &&
  537.         player.ball.pixel.x - mptr->pixel.x < CELL_WIDTH &&
  538.         player.ball.pixel.y - mptr->pixel.y >= 0 &&
  539.         player.ball.pixel.y - mptr->pixel.y < CELL_HEIGHT)
  540.           {
  541.         if(mptr == monster.list)
  542.           {
  543.             player.ball.state = 0;
  544.             player.ball.count = monster.list[0].face;
  545.             player.ball.pixel.x = monster.list[0].pixel.x +
  546.             CELL_WIDTH / 2;
  547.             player.ball.pixel.y = monster.list[0].pixel.y +
  548.             CELL_HEIGHT / 2;
  549.           }
  550.         else
  551.           {
  552.             mptr->shot = 1;
  553.             player.ball.state = 2;
  554.             player.ball.count = 0;
  555.           }
  556.         break;
  557.           }
  558.     }
  559.     /*}}}*/
  560.       break;
  561.     }
  562.     /*}}}*/
  563.     /*{{{  case 2: (explode)*/
  564.     case 2:
  565.       player.ball.count++;
  566.       if(player.ball.count == BALL_EXPLODE)
  567.     player.ball.state = 3;
  568.       break;
  569.     /*}}}*/
  570.     /*{{{  case 3: (exploded)*/
  571.     case 3:
  572.       if(random() < 4)
  573.     {
  574.       player.ball.state = 4;
  575.       player.ball.count--;
  576.     }
  577.       break;
  578.     /*}}}*/
  579.     /*{{{  case 4: (implode)*/
  580.     case 4:
  581.     {
  582.       int       face;
  583.       
  584.       player.ball.count--;
  585.       face = monster.list[0].face;
  586.       player.ball.pixel.x = monster.list[0].pixel.x + CELL_WIDTH / 2;
  587.       player.ball.pixel.y = monster.list[0].pixel.y + CELL_HEIGHT / 2;
  588.       if(!player.ball.count)
  589.     player.ball.state = 0;
  590.       break;
  591.     }
  592.     /*}}}*/
  593.   }
  594.   if(!player.ball.state)
  595.     {
  596.       player.ball.count = monster.list[0].face;
  597.       player.ball.image = monster.list[0].image;
  598.       player.ball.pixel.x = monster.list[0].pixel.x + CELL_WIDTH / 2;
  599.       player.ball.pixel.y = monster.list[0].pixel.y + CELL_HEIGHT / 2;
  600.     }
  601.   return;
  602. }
  603. /*}}}*/
  604. /*{{{  void move_player()*/
  605. extern void move_player FUNCARGVOID
  606. /*
  607.  * moves the player
  608.  * and deals with eating cherries etc
  609.  */
  610. {
  611.   CELL      *cptr;
  612.   unsigned  dir;
  613.  
  614.   dir = monster.list[0].dir;
  615.   /*{{{  motionevent?*/
  616.   if(player.motionevent && !player.keyboard &&
  617.       (!monster.list[0].stop ||
  618.        player.raw_mouse.x - player.mouse.x * (CELL_WIDTH + GAP_WIDTH) >
  619.       BORDER_LEFT + GAP_WIDTH / 2 + (CELL_WIDTH + GAP_WIDTH) / 4 +
  620.       CELL_WIDTH + GAP_WIDTH ||
  621.        player.raw_mouse.y - (int)player.mouse.y * (CELL_HEIGHT + GAP_HEIGHT) >
  622.       BORDER_TOP + GAP_HEIGHT / 2 + (CELL_HEIGHT + GAP_HEIGHT) / 4 +
  623.       CELL_HEIGHT + GAP_HEIGHT ||
  624.        player.raw_mouse.x - (int)player.mouse.x * (CELL_WIDTH + GAP_WIDTH) <
  625.       BORDER_LEFT + GAP_WIDTH / 2 - (GAP_WIDTH + CELL_WIDTH) / 4||
  626.        player.raw_mouse.y - (int)player.mouse.y * (CELL_HEIGHT + GAP_HEIGHT) <
  627.       BORDER_TOP + GAP_HEIGHT / 2 - (GAP_HEIGHT + CELL_HEIGHT) / 4))
  628.     /*
  629.      * for mouse motion, we get the cell number for the mouse, and
  630.      * set dir & mouse dir to point towards it
  631.      */
  632.     {
  633.       int       x, y;
  634.     
  635.       x = (player.raw_mouse.x - BORDER_LEFT - GAP_WIDTH / 2) /
  636.       (GAP_WIDTH + CELL_WIDTH);
  637.       y = (player.raw_mouse.y - BORDER_TOP - GAP_HEIGHT / 2) /
  638.       (GAP_HEIGHT + CELL_HEIGHT);
  639.       /*{{{  clip x*/
  640.       if(x < 0)
  641.     x = 0;
  642.       else if(x > CELLS_ACROSS - 1)
  643.     x = CELLS_ACROSS - 1;
  644.       /*}}}*/
  645.       /*{{{  clip y*/
  646.       if(y < 0)
  647.     y = 0;
  648.       else if(y > CELLS_DOWN - 1)
  649.     y = CELLS_DOWN - 1;
  650.       /*}}}*/
  651.       if(y != player.mouse.y || x != player.mouse.x)
  652.     {
  653.       unsigned  dir;
  654.       unsigned  second;
  655.     
  656.       player.mouse.x = x;
  657.       player.mouse.y = y;
  658.       /*{{{  calc x direction*/
  659.       if(x == monster.list[0].cell.x && !monster.list[0].offset.x)
  660.         x = 0;
  661.       else if(x < monster.list[0].cell.x ||
  662.           (x == monster.list[0].cell.x && monster.list[0].offset.x > 0))
  663.         x = 6;
  664.       else
  665.         x = 7;
  666.       /*}}}*/
  667.       /*{{{  calc y direction*/
  668.       if(y == monster.list[0].cell.y && !monster.list[0].offset.y)
  669.         y = 0;
  670.       else if(y < monster.list[0].cell.y ||
  671.           (y == monster.list[0].cell.y && monster.list[0].offset.y > 0))
  672.         y = 4;
  673.       else
  674.         y = 5;
  675.       /*}}}*/
  676.       /*{{{  select which way round to do them*/
  677.       if(monster.list[0].dir & 2)
  678.         {
  679.           if(monster.list[0].dir != x)
  680.         {
  681.           dir = y;
  682.           second = x;
  683.         }
  684.           else
  685.         {
  686.           dir = x;
  687.           second = y;
  688.         }
  689.         }
  690.       else
  691.         {
  692.           if(monster.list[0].dir != y)
  693.         {
  694.           dir = x;
  695.           second = y;
  696.         }
  697.           else
  698.         {
  699.           dir = y;
  700.           second = x;
  701.         }
  702.         }
  703.       /*}}}*/
  704.       player.next_dir = 0;
  705.       /*{{{  do u turn fiddling*/
  706.       if(!dir)
  707.         dir = second;
  708.       else if(!second)
  709.         second = dir;
  710.       else if(monster.list[0].offset.x && !(dir & 2))
  711.         {
  712.           player.next_dir = dir;
  713.           if(monster.list[0].offset.x < -(CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  714.         dir = 6;
  715.           else if(monster.list[0].offset.x > (CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  716.         dir = 7;
  717.           else if(monster.list[0].offset.x > 0 &&
  718.           monster.list[0].offset.x <= (CELL_WIDTH + GAP_WIDTH) / 4)
  719.         dir = 6;
  720.           else if(monster.list[0].offset.x < 0 &&
  721.           monster.list[0].offset.x >= -(CELL_WIDTH + GAP_WIDTH) / 4)
  722.         dir = 7;
  723.           else
  724.         dir = monster.list[0].dir | 4;
  725.         }
  726.       else if(monster.list[0].offset.y && (dir & 2))
  727.         {
  728.           player.next_dir = dir;
  729.           if(monster.list[0].offset.y < -(CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  730.         dir = 4;
  731.           else if(monster.list[0].offset.y > (CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  732.         dir = 5;
  733.           else if(monster.list[0].offset.y > 0 &&
  734.           monster.list[0].offset.y <= (CELL_HEIGHT + GAP_HEIGHT) / 4)
  735.         dir = 4;
  736.           else if(monster.list[0].offset.y < 0 &&
  737.           monster.list[0].offset.y >= -(CELL_HEIGHT + GAP_HEIGHT) / 4)
  738.         dir = 5;
  739.           else
  740.         dir = monster.list[0].dir | 4;
  741.         }
  742.       /*}}}*/
  743.       monster.list[0].dir = dir & 3;
  744.       monster.list[0].stop = !(dir & 4);
  745.       player.mouse_dir = second;
  746.     }
  747.     }
  748.   /*}}}*/
  749.   /*{{{  key change?*/
  750.   if(player.bashed || (player.old_pressed ^ player.pressed) & 0xF)
  751.   /*
  752.    * The keys have changed, so we need to select a new direction
  753.    * if we're not an interchange to change dir, we keep going
  754.    * in the current direction, if that is non-zero,
  755.    * else we go to the nearest interchange
  756.    */
  757.   {
  758.     unsigned  valid;
  759.     unsigned  pressed;
  760.     
  761.     player.mouse_dir = 0;
  762.     pressed = player.pressed & ~player.bashed;
  763.     if(!pressed)
  764.       pressed = player.pressed;
  765.     valid = 0xF;
  766.     /*{{{  work out valid direction and the edges*/
  767.     if(monster.list[0].offset.x)
  768.       {
  769.     valid &= 0xC;
  770.     if(!monster.list[0].cell.y)
  771.       pressed &= 0xE;
  772.     else if(monster.list[0].cell.y == CELLS_DOWN - 1)
  773.       pressed &= 0xD;
  774.       }
  775.     else if(monster.list[0].offset.y)
  776.       {
  777.     valid &= 0x3;
  778.     if(!monster.list[0].cell.x)
  779.       pressed &= 0xB;
  780.     else if(monster.list[0].cell.x == CELLS_ACROSS - 1)
  781.       pressed &= 0x7;
  782.       }
  783.     else
  784.       {
  785.     if(!monster.list[0].cell.x)
  786.       valid &= 0xB;
  787.     else if(monster.list[0].cell.x == CELLS_ACROSS - 1)
  788.       valid &= 0x7;
  789.     if(!monster.list[0].cell.y)
  790.       valid &= 0xE;
  791.     else if(monster.list[0].cell.y == CELLS_DOWN - 1)
  792.       valid &= 0xD;
  793.     pressed &= valid;
  794.       }
  795.     /*}}}*/
  796.     if((pressed & 0x3) == 0x3)
  797.       pressed &= 0xC;
  798.     if((pressed & 0xC) == 0xC)
  799.       pressed &= 0x3;
  800.     if(!pressed)
  801.       {
  802.     monster.list[0].stop = 1;
  803.     player.next_dir = 0;
  804.       }
  805.     else if((valid & pressed) == pressed)
  806.       {
  807.     unsigned  dir;
  808.     
  809.     if((pressed & 0x3) && (pressed & 0xC))
  810.       pressed &= monster.list[0].dir & 2 ? 0x3 : 0xC;
  811.     for(dir = 0; !(pressed & 1); dir++, pressed >>= 1)
  812.       /*EMPTY*/;
  813.     player.next_dir = 0;
  814.     monster.list[0].dir = dir;
  815.     monster.list[0].stop = 0;
  816.       }
  817.     else
  818.       {
  819.     unsigned  dir;
  820.     
  821.     pressed &= ~valid;
  822.     for(dir = 0; !(pressed & 1); pressed >>= 1)
  823.       dir++;
  824.     player.next_dir = dir | 4;
  825.     if(monster.list[0].stop)
  826.       {
  827.         /*{{{  select nearest cell*/
  828.         if(dir & 2)
  829.           {
  830.         if(monster.list[0].offset.y <
  831.             -(CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  832.           dir = 0;
  833.         else if(monster.list[0].offset.y >
  834.             (CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  835.           dir = 1;
  836.         else if(monster.list[0].offset.y > 0 &&
  837.             monster.list[0].offset.y <=
  838.             (CELL_HEIGHT + GAP_HEIGHT) / 4)
  839.           dir = 0;
  840.         else if(monster.list[0].offset.y < 0 &&
  841.             monster.list[0].offset.y >=
  842.             -(CELL_HEIGHT + GAP_HEIGHT) / 4)
  843.           dir = 1;
  844.         else
  845.           dir = monster.list[0].dir;
  846.           }
  847.         else
  848.           {
  849.         if(monster.list[0].offset.x <
  850.             -(CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  851.           dir = 2;
  852.         else if(monster.list[0].offset.x >
  853.             (CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  854.           dir = 3;
  855.         else if(monster.list[0].offset.x > 0 &&
  856.             monster.list[0].offset.x <=
  857.             (CELL_WIDTH + GAP_WIDTH) / 4)
  858.           dir = 2;
  859.         else if(monster.list[0].offset.x < 0 &&
  860.             monster.list[0].offset.x >=
  861.             -(CELL_WIDTH + GAP_WIDTH) / 4)
  862.           dir = 3;
  863.         else
  864.           dir = monster.list[0].dir;
  865.           }
  866.         /*}}}*/
  867.         monster.list[0].dir = dir;
  868.         monster.list[0].stop = 0;
  869.       }
  870.       }
  871.     if(monster.list[0].stop)
  872.       player.bashed = 0;
  873.     else if(player.bashed == 0x10)
  874.       player.bashed = 0;
  875.     else if(player.bashed & (1 << monster.list[0].dir))
  876.       player.bashed = 0;
  877.     else if(!(player.bashed & (3 << (monster.list[0].dir & 2))))
  878.       player.bashed = 0x10;
  879.   }
  880.   /*}}}*/
  881.   player.old_pressed = player.pressed;
  882.   if(player.throw == 2)
  883.     {
  884.       if(!player.button)
  885.     player.throw = 0;
  886.     }
  887.   else if(player.throw == 0)
  888.     player.throw = player.button;
  889.   if(dir != monster.list[0].dir)
  890.     new_face(&monster.list[0]);
  891.   if(monster.list[0].pause)
  892.     {
  893.       player.cherry = player.distance = 0;
  894.       monster.list[0].pause = 0;
  895.     }
  896.   else if(!monster.list[0].stop)
  897.     {
  898.       if(!monster.list[0].cycle)
  899.     {
  900.       monster.list[0].cycle = MONSTER_CYCLES;
  901.       monster.list[0].image++;
  902.       if(monster.list[0].image == MONSTER_IMAGES)
  903.         monster.list[0].image = 0;
  904.       
  905.     }
  906.       monster.list[0].cycle--;
  907.       cptr = move_muncher(&monster.list[0]);
  908.       /*{{{  pushing?*/
  909.       {
  910.     unsigned  push;
  911.         
  912.     push = monster.list[0].pause && (monster.list[0].dir & 2);
  913.     if(push != monster.list[0].pushing)
  914.       {
  915.         monster.list[0].pushing = push;
  916.         new_face(&monster.list[0]);
  917.       }
  918.       }
  919.       /*}}}*/
  920.       if(monster.list[0].stop)
  921.     {
  922.       monster.list[0].pause = 0;
  923.       player.bashed = 1 << monster.list[0].dir;
  924.     }
  925.       if(cptr)
  926.     {
  927.       if(cptr->sprite == SPRITE_CHERRY)
  928.         /*{{{  eat cherry*/
  929.         {
  930.           cptr->sprite = 0;
  931.           global.cherries--;
  932.           add_score(50, 0, 0);
  933.           player.cherry++;
  934.           if(player.cherry == 8)
  935.         {
  936.           add_score(500,
  937.               monster.list[0].pixel.x + CELL_WIDTH / 2,
  938.               monster.list[0].pixel.y + CELL_HEIGHT / 2);
  939.           player.cherry = 0;
  940.         }
  941.           else
  942.         player.distance =
  943.             (CELL_WIDTH + GAP_WIDTH) / VEL_X;
  944.         }
  945.         /*}}}*/
  946.       else if(cptr->sprite >= SPRITE_PRIZE_BASE &&
  947.           cptr->sprite < SPRITE_PRIZE_BASE + SPRITE_PRIZES)
  948.         /*{{{  eat prize*/
  949.         {
  950.           int     score;
  951.             
  952.           history.prize |= 1;
  953.           cptr->sprite = 0;
  954.           score = player.screen * 500 + 500;
  955.           add_score(score > 9500 ? 9500 : score,
  956.           monster.list[0].pixel.x + CELL_WIDTH / 2,
  957.           monster.list[0].pixel.y + CELL_HEIGHT / 2);
  958.           global.state = 2;
  959.           if(!extra.escape)
  960.         extra_escape();
  961.           monster.den = 3;
  962.           monster.delay = 1;
  963.         }
  964.         /*}}}*/
  965.     }
  966.     }
  967.   if(player.distance)
  968.     player.distance--;
  969.   else
  970.     player.cherry = 0;
  971.   /*{{{  player looping*/
  972.   if(monster.list[0].stop ||
  973.       monster.list[0].offset.x || monster.list[0].offset.y)
  974.     /*EMPTY*/;
  975.   else if(player.mouse_dir &&
  976.       monster.list[0].cell.x == player.mouse.x &&
  977.       monster.list[0].cell.y == player.mouse.y)
  978.     {
  979.       player.next_dir = player.mouse_dir = 0;
  980.       monster.list[0].stop = 1;
  981.     }
  982.   else if(player.mouse_dir &&
  983.       monster.list[0].dir != (player.mouse_dir & 3) &&
  984.       (monster.list[0].cell.x == player.mouse.x ||
  985.        monster.list[0].cell.y == player.mouse.y))
  986.     {
  987.       monster.list[0].dir = player.mouse_dir & 3;
  988.       player.next_dir = 0;
  989.       new_face(&monster.list[0]);
  990.     }
  991.   else if((!monster.list[0].cell.x && monster.list[0].dir == 2) ||
  992.       (!monster.list[0].cell.y && monster.list[0].dir == 0) ||
  993.       (monster.list[0].cell.x == CELLS_ACROSS - 1 &&
  994.       monster.list[0].dir == 3) ||
  995.       (monster.list[0].cell.y == CELLS_DOWN - 1 &&
  996.       monster.list[0].dir == 1))
  997.     {
  998.       player.next_dir = 0;
  999.       monster.list[0].stop = 1;
  1000.       player.bashed = 1 << monster.list[0].dir;
  1001.     }
  1002.   else if(player.next_dir)
  1003.     {
  1004.       monster.list[0].dir = player.next_dir & 3;
  1005.       player.next_dir = 0;
  1006.       new_face(&monster.list[0]);
  1007.     }
  1008.   /*}}}*/
  1009.   if(!monster.list[0].shot)
  1010.     /*{{{  hit monster?*/
  1011.     {
  1012.       unsigned  i;
  1013.       MONSTER   *mptr;
  1014.       int       x, y;
  1015.     
  1016.       x = monster.list[0].pixel.x - CELL_WIDTH + GAP_WIDTH;
  1017.       y = monster.list[0].pixel.y - CELL_HEIGHT + GAP_HEIGHT;
  1018.       for(mptr = &monster.list[1], i = monster.monsters - 1; i--; mptr++)
  1019.     if(!mptr->chew && !mptr->shot && !mptr->apple &&
  1020.         mptr->pixel.x - x > 0 &&
  1021.         mptr->pixel.x - x < 2 * (CELL_WIDTH - GAP_WIDTH) &&
  1022.         mptr->pixel.y - y > 0 &&
  1023.         mptr->pixel.y - y < 2 * (CELL_HEIGHT - GAP_HEIGHT))
  1024.       {
  1025.         monster.list[0].shot = 1;
  1026.         break;
  1027.       }
  1028.     }
  1029.     /*}}}*/
  1030.   return;
  1031. }
  1032. /*}}}*/
  1033.